package com.design.pattern.interpreter;

import com.design.pattern.mediator.Boss;
import com.design.pattern.visitor.user.Teacher;
import com.sun.org.apache.xpath.internal.operations.Bool;

import java.lang.reflect.InvocationTargetException;
import java.security.PublicKey;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 计算接口的上下文,存储数据
 */
public class CalculateContext {
    public static final Map<String, Class<? extends AbstractCalculateInterpreter>> KEY_WORDS_MAP;//计算方式关键字及其对应类
    public static List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> valueMap = new ArrayList<>();//处理值

    static {
        KEY_WORDS_MAP = new HashMap<>();
        //初始化计算子类和值子类
        KEY_WORDS_MAP.put("加", SumCalculateInterpreter.class);//加法
        KEY_WORDS_MAP.put("减", SubCalculateInterpreter.class);//减法
        KEY_WORDS_MAP.put("乘", MultiplicationCalculateInterpreter.class);//乘法
        KEY_WORDS_MAP.put("除", DivisionCalculateInterpreter.class);//除法
    }

    /**
     * 执行解析调用
     *
     * @param exp 被解释的数据
     * @return 结果
     */
    public static Double doHandler(String exp) {
        //第一步,生成正则
        String regex = getRegex();
        //第二步,处理values,并使用计算类间隔开来,形成由CalculateInterpreter子类构成的集合.
        List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> values = getAllValues(exp, regex);
        //第三步,生成运算队列
        // sort(values);
        //第四步,进行处理
        values = sortUtils(values, MultiplicationCalculateInterpreter.class, DivisionCalculateInterpreter.class, true);
        valueMap = sortUtils(values, SumCalculateInterpreter.class, SubCalculateInterpreter.class, false);
        return handler();
    }

    public static double handler() {
        //倒序计算
        for (int i = valueMap.size() - 2; i > 0; i--) {//减2是去除最后一个元素
            ((AbstractCalculateInterpreter) (valueMap.get(i).values().toArray()[0])).setPre(((AbstractCalculateInterpreter) (valueMap.get(i - 1).values().toArray()[0])));

        }

        return ((CalculateInterpreter) (valueMap.get(valueMap.size() - 2).values().toArray()[0])).interpreter();
    }

    public static List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> sortUtils(List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> valueMap
            , Class<? extends AbstractCalculateInterpreter> clazzA, Class<? extends AbstractCalculateInterpreter> clazzB, Boolean flag
    ) {
        //获取最后的角标
        StringBuffer stringBuffer = new StringBuffer();
        for (int i = 0; i < valueMap.size(); i++) {
            Map<Class<? extends CalculateInterpreter>, CalculateInterpreter> value = valueMap.get(i);//获取当前元素
            Class clazz = null;
            for (Class claz : value.keySet()) {
                clazz = claz;
            }
            if (clazz.equals(clazzA) || clazz.equals(clazzB)) {

                CalculateInterpreter pre = (CalculateInterpreter) valueMap.get(i - 1).get(valueMap.get(i - 1).keySet().toArray()[0]);
                stringBuffer.append(i - 1).append(",");
                CalculateInterpreter next = (CalculateInterpreter) valueMap.get(i + 1).get(valueMap.get(i + 1).keySet().toArray()[0]);
                //如果是乘除法还需要删除掉后面的元素
                if (flag) {
                    stringBuffer.append(i + 1).append(",");
                }
                CalculateInterpreter calculateInterpreter = null;
                try {
                    valueMap.set(i, toMap(clazz, getClassInstance(clazz, pre, next)));//重新赋值
                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                } catch (InstantiationException e) {
                    e.printStackTrace();
                }
            }
        }
        //已经获取到需要优先计算的数据,移除无效数据
        if (null != stringBuffer && stringBuffer.length() > 0) {
            String[] indexs = stringBuffer.substring(0, stringBuffer.length() - 1).toString().split(",");
            List tmpList = new ArrayList();
            tmpList.addAll(valueMap);
            for (String index : indexs) {
                int i = Integer.valueOf(index);
                valueMap.remove(tmpList.get(i));
            }
        }
        return valueMap;
    }

    /**
     * 匹配正则,获取数据队列
     *
     * @param exp   字符串
     * @param regex 正则
     * @return map
     */
    public static List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> getAllValues(String exp, String regex) {
        List<Map<Class<? extends CalculateInterpreter>, CalculateInterpreter>> result = new ArrayList<>();
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(exp);
        int index = 0;
        while (matcher.find()) {
            //当正则匹配到元素的时候,处理字符数据
            //获取匹配到的字符内容
            String regKey = exp.substring(matcher.start(), matcher.end());
            //根据上次匹配的值,获取到匹配前的内容
            String preValue = exp.substring(index, matcher.start());
            result.add(toMap(ValueInterpreter.class, new ValueInterpreter(Double.valueOf(preValue))));
            result.add(toMap(KEY_WORDS_MAP.get(regKey), null));
            //重置角标
            index = matcher.end();
        }
        //处理最后一个元素
        if (index != 0) {
            result.add(toMap(ValueInterpreter.class, new ValueInterpreter(Double.valueOf(exp.substring(index)))));
        }
        return result;
    }

    /**
     * 获取MAP
     *
     * @param clazz    类型
     * @param instance 实例
     * @return map
     */
    public static Map<Class<? extends CalculateInterpreter>, CalculateInterpreter> toMap(Class<? extends CalculateInterpreter> clazz, CalculateInterpreter instance) {
        Map<Class<? extends CalculateInterpreter>, CalculateInterpreter> tmpMap = new HashMap<>();
        tmpMap.put(clazz, instance);
        return tmpMap;
    }

    /**
     * 生成正则
     *
     * @return 生成正则
     */
    public static String getRegex() {
        String prefix = "[";//前缀
        String split = "|";//分隔符
        String suffix = "]";//后缀
        StringBuffer result = new StringBuffer(prefix);
        for (String subRegex : KEY_WORDS_MAP.keySet()) {
            result.append(subRegex).append(split);
        }
        //处理最后一个分隔符,并返回正则
        return result.substring(0, result.length() - 1) + suffix;
    }


    /**
     * 获取实例
     *
     * @param clazz 类实例类型
     * @param pre   第一个构造参数
     * @param next  第二个构造参数
     * @return 具体实例
     * @throws NoSuchMethodException     没有找到构造方法异常
     * @throws IllegalAccessException    权限异常
     * @throws InvocationTargetException 执行一场
     * @throws InstantiationException    实例异常
     */
    public static CalculateInterpreter getClassInstance(Class<? extends CalculateInterpreter> clazz, CalculateInterpreter pre, CalculateInterpreter next) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        return clazz.getConstructor(CalculateInterpreter.class, CalculateInterpreter.class).newInstance(pre, next);
    }
}
